package cn.tb.ymcc.service.impl;

import cn.tb.ymcc.constants.CommonConstants;
import cn.tb.ymcc.constants.YmccCode;
import cn.tb.ymcc.constants.SmsCodeConstants;
import cn.tb.ymcc.domain.BlacklistSms;
import cn.tb.ymcc.domain.MessageSms;
import cn.tb.ymcc.dto.RedisRegisterDto;
import cn.tb.ymcc.dto.RegisterDto;
import cn.tb.ymcc.exception.GlobleException;
import cn.tb.ymcc.service.IVerifyCodeService;
import cn.tb.ymcc.util.AssertUtil;
import cn.tb.ymcc.util.StrUtils;
import cn.tb.ymcc.util.VerifyCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;
    @Autowired
    private MessageSmsServiceImpl messageSmsService;
    @Autowired
    private SmsCodeConstants smsCodeConstants;
    @Autowired
    private BlacklistSmsServiceImpl blacklistSmsService;

    /**
     * 图片验证码
     * @param key
     * @return
     */
    @Override
    public String imgCode(String key) {
        if(!StringUtils.hasLength(key)){
            throw new GlobleException(YmccCode.COMMON_IMGCODEKEY_NOT_NULL.getCode(),YmccCode.COMMON_IMGCODEKEY_NOT_NULL.getMessage());
        }
        //生成code
        String code = StrUtils.getComplexRandomString(4);
        //保存到redis，设置过期的时间
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //用Base64编码成字符串，返回Base64编码的字符串
        return VerifyCodeUtils.verifyCode(100,40,code);
    }

    /**
     * 短信验证码
     * @param dto
     */
    @Override
    public void smsCode(RegisterDto dto) {
        Integer regChannel = dto.getRegChannel();

        if(regChannel==null){
            throw new GlobleException("注册渠道不能为空");
        }
        if(regChannel==1){
            registerCode(dto);
        }
    }

    /**
     * 发送短信验证码逻辑
     * @param dto
     */
    public void registerCode(RegisterDto dto) {
        String imageCode = dto.getImageCode();
        String imageCodeKey = dto.getImageCodeKey();
        String mobile = dto.getMobile();

        BlacklistSms blacklistSms = blacklistSmsService.loadByMobile(mobile);
        AssertUtil.isNull(blacklistSms,"你是黑名单号码！懂？");
        AssertUtil.isNotNull(imageCode,YmccCode.COMMON_IMGCODE_NOT_NULL.getMessage());
        //2.判断图形验证码是否一致,根据imageCodeKey从Redis中获取
        //2.1获取到了,跟前端填写的图片验证码做比较
        Object imgCodeTmp = redisTemplate.opsForValue().get(imageCodeKey);
        String imgCodeTmp1 = (String) imgCodeTmp;
        AssertUtil.isEqualsIgnoreCase(imgCodeTmp1,imageCode,YmccCode.COMMON_IMGCODE_NOT_EQUALS.getMessage());

//        if(imgCodeTmp.toString().equals(imageCode)){
//            throw new GlobleException(YmccCode.COMMON_IMGCODE_NOT_EQUALS.getMessage());
//        }
        //2.2获取不到，验证码过期
        AssertUtil.isNotNull(imgCodeTmp1,YmccCode.COMMON_IMGCODE_TIMEOUT.getMessage());

//        if(imgCodeTmp==null){
//            throw new GlobleException(YmccCode.COMMON_IMGCODE_TIMEOUT.getMessage());
//        }
        String businessKey = String.format(CommonConstants.REGISTER_PHONE_PRIFIX,dto.getMobile());
        sendSmsCode(businessKey,dto);
    }

    /**
     * 发送短信验证码
     * @param businessKey
     */
    private void sendSmsCode(String businessKey,RegisterDto dto) {
        //4.短信验证码
        //根据电话号码拼接key,从Redis中获取曾经可能有的短信验证码
        String key = businessKey;
        Object smsCodeTmp = redisTemplate.opsForValue().get(key);
        String code = "";
        Date now = new Date();

        //4.1 获取到了,校验是否超过重发时间
        if (smsCodeTmp != null) {
            RedisRegisterDto redisRegisterDto = (RedisRegisterDto) smsCodeTmp;
            //4.1.1重发时间还没到
            Boolean can = now.getTime()-redisRegisterDto.getTime() < smsCodeConstants.getInterval();
            AssertUtil.isFalse(can,YmccCode.COMMON_SERIOUS.getMessage());
//            if (now.getTime() - redisRegisterDto.getTime() < 60 * 1000) {
//                throw new GlobleException(YmccCode.COMMON_SERIOUS.getCode(),YmccCode.COMMON_SERIOUS.getMessage());
//            }
            code = redisRegisterDto.getCode();
            //4.2 获取不到,生成新的短信验证码
        }else{
        //生成验证码
        code = StrUtils.getComplexRandomString(smsCodeConstants.getSize());
        }

        //5 存储Redis，并设置一个过期时间
        RedisRegisterDto redisRegisterDto = new RedisRegisterDto(code,now.getTime());
        redisTemplate.opsForValue().set(key,redisRegisterDto,smsCodeConstants.getTimeout(), TimeUnit.MINUTES);
        //6 发送短信
        //SmsUtils.sendSms(dto.getPhone(),"亲，您的短信验证码是："+smsCode+"，三分钟之内有效哦！");
        String message = String.format(smsCodeConstants.getSmsmessage(), code);

        log.info(message);
        //存储到messageSms表
        saveMessageSms(now, code, message,dto);
    }

    private void saveMessageSms(Date now, String code,String message,RegisterDto dto) {
        MessageSms messageSms = new MessageSms();
        messageSms.setMobile(dto.getMobile());
        messageSms.setContent(message);
        messageSms.setSendTime(now);
        messageSms.setTitle(smsCodeConstants.getTitle());
        // 获取请求体 request
        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = ((ServletRequestAttributes) requestAttributes).getRequest();
        //获取IP地址
        messageSms.setIp(request.getRemoteAddr());
        messageSmsService.insert(messageSms);
    }
}

